{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/Ziqi/anaconda/lib/python3.5/site-packages/libpysal/io/iohandlers/__init__.py:25: UserWarning: SQLAlchemy and Geomet not installed, database I/O disabled\n",
      "  warnings.warn('SQLAlchemy and Geomet not installed, database I/O disabled')\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import geopandas as gp\n",
    "import multiprocessing as mp\n",
    "import libpysal as ps\n",
    "import sys\n",
    "sys.path.append('/Users/Ziqi/Desktop/mgwr/')\n",
    "from mgwr.gwr import GWR,MGWR\n",
    "from mgwr.sel_bw import Sel_BW"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Load Berlin example\n",
    "prenz = gp.read_file(ps.examples.get_path('prenzlauer.zip'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "b_y = np.log(prenz['price'].values.reshape((-1, 1)))\n",
    "b_X = prenz[['review_sco','accommodat','bathrooms']].values \n",
    "b_X = (b_X - b_X.mean(axis=0)) / b_X.std(axis=0)\n",
    "b_y = (b_y - b_y.mean(axis=0)) / b_y.std(axis=0)\n",
    "u = prenz['X']\n",
    "v = prenz['Y']\n",
    "b_coords = list(zip(u, v))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "env: OMP_NUM_THREADS=1\n"
     ]
    }
   ],
   "source": [
    "#This might be needed to turn off the OpenMP multi-threading\n",
    "%env OMP_NUM_THREADS = 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### GWR No Parallel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "192.0\n",
      "CPU times: user 13.9 s, sys: 116 ms, total: 14 s\n",
      "Wall time: 14.2 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "gwr_selector = Sel_BW(b_coords, b_y, b_X)\n",
    "gwr_bw = gwr_selector.search()\n",
    "print(gwr_bw)\n",
    "gwr_results = GWR(b_coords, b_y, b_X, gwr_bw).fit()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### MGWR No Parallel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 191. 1279.   79. 2200.]\n",
      "CPU times: user 3min 37s, sys: 2.73 s, total: 3min 40s\n",
      "Wall time: 3min 18s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "mgwr_selector = Sel_BW(b_coords, b_y, b_X, multi=True)\n",
    "mgwr_bw = mgwr_selector.search()\n",
    "print(mgwr_bw)\n",
    "mgwr_results = MGWR(b_coords, b_y, b_X, selector=mgwr_selector).fit()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Parrallelization is more favored when you your data are large and/or your machine have many many cores.\n",
    "#mgwr has soft dependency of numba, please install numba if you need better performance (pip install numba).\n",
    "\n",
    "n_proc = 2 #two processors\n",
    "pool = mp.Pool(n_proc) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### GWR Parallel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "192.0\n",
      "CPU times: user 303 ms, sys: 42.3 ms, total: 346 ms\n",
      "Wall time: 7.05 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "gwr_selector = Sel_BW(b_coords, b_y, b_X)\n",
    "gwr_bw = gwr_selector.search(pool=pool) #add pool to Sel_BW.search\n",
    "print(gwr_bw)\n",
    "gwr_results = GWR(b_coords, b_y, b_X, gwr_bw).fit(pool=pool) #add pool to GWR.fit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### MGWR Parallel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 191. 1279.   79. 2200.]\n",
      "CPU times: user 5.08 s, sys: 388 ms, total: 5.46 s\n",
      "Wall time: 2min 2s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "mgwr_selector = Sel_BW(b_coords, b_y, b_X, multi=True)\n",
    "mgwr_bw = mgwr_selector.search(pool=pool) #add pool to Sel_BW.search\n",
    "print(mgwr_bw)\n",
    "mgwr_results = MGWR(b_coords, b_y, b_X, selector=mgwr_selector).fit(pool=pool) #add pool to MGWR.fit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "pool.close() # Close the pool when you finish\n",
    "pool.join()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [default]",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
